from sqlalchemy.orm import Session
from typing import Tuple, Union, List, Type
from db import models
from schemas.images import UploadImage, UpdateImageTags, CreateImageFolder, UpdateImageFolder
from datetime import datetime


class Images:
    @staticmethod
    def create(db: Session, data: UploadImage) -> models.Images:
        item = models.Images(tags=data.tags,
                             folder=data.folder,
                             upload_time=data.upload_time,
                             width=data.width,
                             height=data.height,
                             size=data.size,
                             hash=data.hash,
                             format=data.format)
        db.add(item)

        folder = db.query(models.ImagesFolder).get(data.folder)
        folder.size += data.size
        folder.count += 1
        db.add(folder)
        db.commit()
        return item

    @staticmethod
    def gets(db: Session, page: int, per_page: int, folder: int) -> Tuple[int, List[models.Images]]:
        count = db.query(models.Images).filter_by(folder=folder).count()
        res = db.query(
            models.Images.id,
            models.Images.width,
            models.Images.height,
            models.Images.hash,
            models.Images.folder,
            models.Images.format).filter_by(folder=folder).order_by(
            models.Images.id.desc()).offset(page * per_page).limit(per_page).all()

        return count, res

    @staticmethod
    def get(db: Session, image_id: int) -> Union[models.Images, None]:
        return db.query(models.Images).get(image_id)

    @staticmethod
    def search(db: Session, kw: str) -> List[Type[models.Images]]:
        return db.query(models.Images).filter(models.Images.tags.like(f"%{kw}%")).all()

    @staticmethod
    def get_by_hash(db: Session, folder: int, image_hash: str) -> Union[models.Images, None]:
        return db.query(models.Images).filter_by(folder=folder, hash=image_hash).first()

    @staticmethod
    def delete(db: Session, image_id: int) -> models.Images:
        item = db.query(models.Images).get(image_id)
        db.delete(item)

        folder = db.query(models.ImagesFolder).get(item.folder)
        folder.size -= item.size
        folder.count -= 1
        db.add(folder)

        db.commit()
        return item

    @staticmethod
    def update_tags(db: Session, data: UpdateImageTags) -> models.Images:
        img = db.query(models.Images).get(data.id)
        img.tags = data.tags

        db.add(img)
        db.commit()
        return img


class ImagesFolder:
    pass

    @staticmethod
    def get_by_name(db: Session, name: str) -> Union[models.ImagesFolder, None]:
        return db.query(models.ImagesFolder).filter_by(name=name).first()

    @staticmethod
    def gets(db: Session) -> List[Type[models.ImagesFolder]]:
        return db.query(models.ImagesFolder).all()

    @staticmethod
    def get(db: Session, folder_id: int) -> Union[models.ImagesFolder, None]:
        return db.query(models.ImagesFolder).get(folder_id)

    @staticmethod
    def create(db: Session, data: CreateImageFolder) -> models.ImagesFolder:
        item = models.ImagesFolder(name=data.name, description=data.description, created_time=datetime.now())
        db.add(item)
        db.commit()
        return item

    @staticmethod
    def update(db: Session, data: UpdateImageFolder) -> Union[models.ImagesFolder, None]:
        item = db.query(models.ImagesFolder).get(data.id)
        if item is not None:
            item.name = data.name
            item.description = data.description
            item.updated_time = datetime.now()
            db.add(item)
            db.commit()
        return item

    @staticmethod
    def delete(db: Session, id_: int) -> Union[models.ImagesFolder, None]:
        item = db.query(models.ImagesFolder).get(id_)
        if item is not None:
            db.delete(item)
            db.commit()
        return item

    @staticmethod
    def get_cover(db: Session, id_: int) -> Union[models.Images, None]:
        return db.query(models.Images).order_by(models.Images.id.desc()).filter(models.Images.folder == id_).first()
